package com.flame.session.service;

import java.time.Duration;
import java.time.Instant;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;

import com.flame.auth.core.constants.AuthConstants;
import com.flame.auth.core.entity.TrustedPrincipal;
import com.flame.session.controller.vo.OnlineUserVo;
import com.flame.session.entity.OnlineUser;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.session.Session;
import org.springframework.session.SessionRepository;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

/**
 * RedisOnlineUserService
 *
 * @author wuxintong
 * @since 2023/3/2
 */
public class RedisOnlineUserServiceImpl implements OnlineUserService {

    private static final String REDIS_SESSION_KEY_PREFIX = "spring:session:sessions:";

    @Autowired
    private SessionRepository sessionRepository;

    @Autowired
    private StringRedisTemplate redisTemplate;

    @Override
    public List<OnlineUser> list(OnlineUserVo onlineUserVo) {
        Set<String> sessinIdList = redisTemplate.keys(REDIS_SESSION_KEY_PREFIX + "*");
        if (CollectionUtils.isEmpty(sessinIdList)) {
            return new ArrayList<>();
        }

        List<OnlineUser> onlineUserList = new ArrayList<>();
        for (String redisSessionKey : sessinIdList) {
            if (redisSessionKey.contains("expires")) {
                continue;
            }
            String sessionId = redisSessionKey.substring(24);
            Session session = sessionRepository.findById(sessionId);
            if (session == null) {
                continue;
            }
            TrustedPrincipal trustedPrincipal = session.getAttribute(AuthConstants.TRUSTED_PRINCIPAL);

            OnlineUser onlineUser = new OnlineUser();
            onlineUser.setPrimaryId(sessionId);
            onlineUser.setSessionId(sessionId);
            if (trustedPrincipal != null) {
                onlineUser.setAccount(trustedPrincipal.getAccount());
                onlineUser.setUserName(trustedPrincipal.getUserName());
                onlineUser.setOrgCode(trustedPrincipal.getOrgCode());
                onlineUser.setIp(trustedPrincipal.getIp());
            } else {
                onlineUser.setAccount("无");
                onlineUser.setUserName("游客");
            }
            onlineUserList.add(onlineUser);
        }

        return onlineUserList.stream().filter(onlineUser -> {
            if (StringUtils.hasText(onlineUserVo.getUserId())) {
                return onlineUser.getAccount().contains(onlineUserVo.getUserId());
            }
            return true;
        }).filter(onlineUser -> {
            if (StringUtils.hasText(onlineUserVo.getUserName())) {
                return onlineUser.getUserName().contains(onlineUserVo.getUserName());
            }
            return true;
        }).collect(Collectors.toList());
    }

    @Override
    public void forceLogout(String primaryId) {
        redisTemplate.delete(REDIS_SESSION_KEY_PREFIX + primaryId);
        redisTemplate.delete(REDIS_SESSION_KEY_PREFIX + "expires:" + primaryId);
    }
}
